package life.sweet.community.service;

import life.sweet.community.dto.CommentDTO;
import life.sweet.community.enums.CommentTypeEnum;
import life.sweet.community.enums.NotificationStstusEnum;
import life.sweet.community.enums.NotificationTypeEnum;
import life.sweet.community.exception.CustomException;
import life.sweet.community.exception.CustomErrorCode;
import life.sweet.community.mapper.*;
import life.sweet.community.model.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CommentService {
    @Autowired
    private QuestionMapper questionMapper;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private QuestionExtMapper questionExtMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private CommentExtMapper commentExtMapper;

    @Autowired
    private NotificationMapper notificationMapper;

    @Transactional
    public void insert(Comment comment, User commentator) {
        if (comment.getParentId() == null || comment.getParentId() == 0) {
            throw new CustomException(CustomErrorCode.TARGET_PARAM_NOT_FOUND);
        }
        if (comment.getType() == null || !CommentTypeEnum.isExist(comment.getType())) {
            throw new CustomException(CustomErrorCode.TYPE_PARAM_WRONG);
        }

        if (comment.getType() == CommentTypeEnum.COMMENT.getType()) {
            // 回复的是评论
            Comment dbComment = commentMapper.selectByPrimaryKey(comment.getParentId());
            if (dbComment == null) {
                throw new CustomException(CustomErrorCode.COMMENT_NOT_FOUND);
            }
            // 评论所在的问题
            Question question = questionMapper.selectByPrimaryKey(dbComment.getParentId());
            if (question == null) {
                throw new CustomException(CustomErrorCode.QUESTION_NOT_FOUND);
            }
            commentMapper.insertSelective(comment);
            dbComment.setCommentCount(1);
            commentExtMapper.incComment(dbComment);
            // 回复评论后 通知 评论发布者
            createNotifiy(comment,dbComment.getCommentator(),commentator.getName(),
                          question.getTitle(),NotificationTypeEnum.REPLY_COMMENT,question.getId());
        } else {
            // 回复问题
            Question dbQuestion = questionMapper.selectByPrimaryKey(comment.getParentId());
            if (dbQuestion == null) {
                throw new CustomException(CustomErrorCode.QUESTION_NOT_FOUND);
            }
            commentMapper.insertSelective(comment);
            dbQuestion.setCommentCount(1); //自增1（防止多线程造成错误）
            questionExtMapper.incComment(dbQuestion);
            // 回复问题后 通知 评论发布者
            createNotifiy(comment,dbQuestion.getCreator(),commentator.getName(),
                          dbQuestion.getTitle(),NotificationTypeEnum.REPLY_QUESTION,dbQuestion.getId());
        }

    }

    private void createNotifiy(Comment comment, Long receiver,String notifierName,
                               String outerTitle,NotificationTypeEnum notificationTypeEnum,Long questionId) {
        if(receiver == comment.getCommentator()) { // 排除自己回复自己评论的通知
            return;
        }
        Notification notification = new Notification();
        notification.setType(notificationTypeEnum.getType());
        notification.setGmtCreate(System.currentTimeMillis());
        notification.setNotifier(comment.getCommentator());
        notification.setStatus(NotificationStstusEnum.UNREAD.getStatus());
        notification.setReceiver(receiver);
        notification.setOuterId(questionId);

        notification.setNotifierName(notifierName);
        notification.setOuterTitle(outerTitle);
        notificationMapper.insertSelective(notification);

    }

    public List<CommentDTO> listByQuestionId(Long parentId, CommentTypeEnum type) {
        CommentExample example = new CommentExample();
        example.createCriteria().andParentIdEqualTo(parentId).andTypeEqualTo(type.getType());
        example.setOrderByClause("gmt_create desc");
        List<Comment> commentList = commentMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(commentList)) {
            return new ArrayList<>();
        }
        Set<Long> userIds = commentList.stream().map(comment -> comment.getCommentator()).collect(Collectors.toSet());
        List<Long> userIdList = new ArrayList<>();
        userIdList.addAll(userIds);
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdIn(userIdList);
        List<User> users = userMapper.selectByExample(userExample);

        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(user -> user.getId(), user -> user));
        List<CommentDTO> comments = commentList.stream().map(comment -> {
            CommentDTO commentDTO = new CommentDTO();
            BeanUtils.copyProperties(comment, commentDTO);
            commentDTO.setUser(userMap.get(comment.getCommentator()));
            return commentDTO;
        }).collect(Collectors.toList());
        return comments;

    }
}
